import json
import os
import traceback
import threading
import shortuuid
import base64
import datetime


# Create your views here.
from django.http import JsonResponse, StreamingHttpResponse

#对话生成
from bid.ai_generate.ai_qa_gen import ai_qa_gen, dify_searchdb, dify_stop, generate_type, system_intention, operate_intention
from bid.ai_generate.projectFilter import extract_project_info
from bid.ai_generate.teamFilter import team_filter
from bid.ai_generate.get_team import get_team
from bid.ai_generate.get_project import get_project
from bid.ai_generate.ai_qa_gen import json_process

#全局变量
global_thread = {
    'chat': {}
}

#获取知识库表接口
# _,table_struct = dify_searchdb()

import time
from functools import wraps

def timing_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"Function {func.__name__!r} executed in {(end_time - start_time)*1000:.2f}ms")
        return result
    return wrapper

#文本基于url的base64编码(+替换成-，/替换成_，=替换成.)
def url_bs64_encode(string):
    bs64_str = str(base64.b64encode(string.encode("utf-8")), "utf-8")
    return  bs64_str.replace('+','-').replace('/','_').replace('=','.')

#文本基于url的base64解码(-替换成+，.替换成=)
def url_bs64_decode(string):
    bs64_str = string.replace('-','+').replace('_','/').replace('.','=')
    return  base64.b64decode(bs64_str).decode()

#判断是否登录
def has_permission(request):

    # session没有token，则未登录
    session_token = request.session.get('token')
    if not session_token:
        return False

    # 如果未传入token，则未登录
    request_token = request.META.get('HTTP_TOKEN')
    if not request_token:
        return False

    #如果都传入，则比对是否一致
    if session_token == request_token:
        return True
    else:
        return False

class chat_thread(threading.Thread):
    def __init__(self, _type, text, task_id, account):
        super(chat_thread, self).__init__()
        self._type = _type
        self.text = text
        self.task_id = task_id
        self.account = account

    def run(self):

        try:

            #sql查询结果
            sql_md = global_thread[self._type][self.task_id]['sql_md']

            #对话id
            conversation_id = global_thread[self._type][self.task_id]['conversation_id']

            #sql查询结果
            results = global_thread[self._type][self.task_id]['results']

            #任务id
            task_id = global_thread[self._type][self.task_id]['task_id']

            # 业务域意图
            system = global_thread[self._type][self.task_id]['system']

            # 操作意图
            operate = global_thread[self._type][self.task_id]['operate']

            # print([sql_md, conversation_id])
            # print(system, operate)

            # 用一次置空即可
            # global_thread[self._type][self.task_id]['sql_md'] = ''
            #
            # # 流式
            # re_content = ai_qa_gen({}, self.text, sql_md, conversation_id, results, self.account,
            #                        global_thread[self._type][self.task_id]['system'], global_thread[self._type][self.task_id]['operate'])
            #
            # # 将生成器带过去
            # global_thread[self._type][self.task_id]['re_content'] = re_content
            # global_thread[self._type][self.task_id]['generate'] = False
            #
            # return

            # 业务域意图识别
            try:
                global_thread[self._type][self.task_id]['system'], error = system_intention(self.text, system, self.account)

                if error:
                    #有错误直接终止
                    global_thread[self._type][self.task_id]['generate'] = True
                    global_thread[self._type][self.task_id]['save_path'] = error
                    return
            except:
                #大模型错误
                print('大模型错误')
                global_thread[self._type][self.task_id]['generate'] = True
                global_thread[self._type][self.task_id]['save_path'] = f"大模型连接错误"
                return

            print('---------------------业务域意图：',global_thread[self._type][self.task_id]['system'])

            #操作意图识别
            try:
                global_thread[self._type][self.task_id]['operate'], error = operate_intention(self.text, operate)

                if error:
                    # 有错误直接终止
                    global_thread[self._type][self.task_id]['generate'] = True
                    global_thread[self._type][self.task_id]['save_path'] = error
                    return
            except:
                # 大模型错误
                print('大模型错误')
                global_thread[self._type][self.task_id]['generate'] = True
                global_thread[self._type][self.task_id]['save_path'] = f"大模型连接错误"
                return

            print('---------------------操作意图：', global_thread[self._type][self.task_id]['operate'])

            # 用一次置空即可
            global_thread[self._type][self.task_id]['sql_md'] = ''

            # 流式
            re_content = ai_qa_gen({}, self.text, sql_md, conversation_id, results, self.account, global_thread[self._type][self.task_id]['operate'])

            # 将生成器带过去
            global_thread[self._type][self.task_id]['re_content'] = re_content
            global_thread[self._type][self.task_id]['generate'] = False

            return

            if intention == "根据条件进行业绩数据筛选":

                # 流式
                re_content = extract_project_info(self.text, task_id, conversation_id)

                # 将生成器带过去
                global_thread[self._type][self.task_id]['re_content'] = re_content
                global_thread[self._type][self.task_id]['generate'] = False

            elif intention == "根据条件进行团队数据筛选":
                # 流式
                re_content = team_filter(self.text, task_id, conversation_id)

                # 将生成器带过去
                global_thread[self._type][self.task_id]['re_content'] = re_content
                global_thread[self._type][self.task_id]['generate'] = False

            else:
                # 先查看是否为生成指令
                query_type = generate_type(self.text)

                if query_type == '其他':

                    # 用一次置空即可
                    global_thread[self._type][self.task_id]['sql_md'] = ''

                    # 流式
                    re_content = ai_qa_gen(table_struct, self.text, sql_md, conversation_id,results)

                    # 将生成器带过去
                    global_thread[self._type][self.task_id]['re_content'] = re_content
                    global_thread[self._type][self.task_id]['generate'] = False
                    # try:
                    #     content_text = next(re_content)
                    #     global_thread[self._type][self.task_id]['content_text'] = content_text
                    # except:
                    #     global_thread[self._type][self.task_id]['content_text'] = 'error'

                else:
                    global_thread[self._type][self.task_id]['generate'] = True
                    results = global_thread[self._type][self.task_id]['results']

                    if len(results) == 0:
                        print('还未选择数据')
                        global_thread[self._type][self.task_id]['save_path'] = f"\n还未选择数据"
                    else:
                        # 提取id
                        ids = [i[0] for i in results]

                        if query_type == '公司业绩':
                            # 生成公司业绩
                            print('生成公司业绩', ids)
                            filename, save_path = get_project('project', ids)
                        elif query_type == '负责人业绩':
                            # 生成负责人业绩
                            print('生成负责人业绩', ids)
                            filename, save_path = get_project('pmProject', ids)
                        elif query_type == '团队管理':
                            # 生成团队管理
                            print('生成团队管理', ids)
                            filename, save_path = get_team('team', ids)


                        download_url = f"/api/bid/get_file?path={url_bs64_encode(save_path)}"
                        global_thread[self._type][self.task_id]['save_path'] = f'\n下载链接：<a href="{download_url}">{filename}</a>'

        except:
            print(traceback.format_exc())

#投标文件问答发送接口
def chat(request):
    if request.method == 'POST':

        # 使用的task_id
        task_id = request.POST.get('task_id')
        # 上传的提示词
        text = request.POST.get('text')
        _type = request.POST.get('type')


        if not text:
            res = {
                'code': 0,
                'msg': "聊天发送内容为空。"
            }
            return JsonResponse(res)

        if not _type:
            res = {
                'code': 0,
                'msg': "任务类型不能为空。"
            }
            return JsonResponse(res)

        if _type not in ['chat']:
            res = {
                'code': 0,
                'msg': "任务类型只能为chat。"
            }
            return JsonResponse(res)

        # 生成唯一任务id
        if not task_id or task_id not in global_thread[_type].keys():
            task_id = str(shortuuid.uuid())
            while task_id in global_thread[_type].keys():
                task_id = str(shortuuid.uuid())

        #放到内存中
        if task_id not in global_thread[_type].keys():
            # 初始sql结果和对话id
            global_thread[_type][task_id] = {"sql_md":"","conversation_id":"","results":[],"task_id":"",'system':'', 'operate':""}

        job = chat_thread(_type, text, task_id, request.session['account'])
        job.start()

        #放入到内存中
        global_thread[_type][task_id]['job'] = job
        # 标识是否持续流式输出，默认为True
        global_thread[_type][task_id]['stream'] = True
        #任务创建时间
        global_thread[_type][task_id]['create_time'] = datetime.datetime.now()

        res = {
            'code': 1,
            'task_id': task_id,
            'msg': "发送成功"
        }
        return JsonResponse(res)
    else:
        res = {
            'code': 0,
            'msg': "不支持的请求方法"
        }
        return JsonResponse(res)

#大瓦特聊天内容流式回复
def stream_response(_type, task_id):

    #如果generate为True，表示生成文件，则返回文件连接
    if global_thread[_type][task_id]['generate']:
        yield global_thread[_type][task_id]['save_path']
        return

    #停止输出
    if not global_thread[_type][task_id]['stream']:
        return

    #大瓦特聊天
    # 将生成器带过去
    re_content = global_thread[_type][task_id]['re_content']
    answer = ''

    # 判断第一次是否有值
    try:
        # 停止输出
        if not global_thread[_type][task_id]['stream']:
            return
        # content_text = global_thread[_type][task_id]['content_text']
        content_text = next(re_content)
        # print([content_text])
        content_text_split = content_text.split('\t')
        reply = '\t'.join(content_text_split[2:])
        global_thread[_type][task_id]['conversation_id'] = content_text_split[1]
        global_thread[_type][task_id]['task_id'] = content_text_split[0]
        # yield f'message {{"text": "{content_text}"}}\n\n'
        answer += reply
        yield reply
    except StopIteration as e:

        print(traceback.format_exc())

        try:
            conversation_id, sql_md, results = e.value
            global_thread[_type][task_id]['sql_md'] = sql_md
            # global_thread[_type][task_id]['conversation_id'] = conversation_id
            global_thread[_type][task_id]['results'] = results
        except:
            pass

        # 大瓦特没有响应
        # yield f'message {{"text": "大瓦特没有响应"}}\n\n'
        yield "大瓦特没有响应"
        return

    try:
        while True:
            # 停止输出
            if not global_thread[_type][task_id]['stream']:
                return
            content_text = next(re_content)
            content_text_split = content_text.split('\t')
            reply = '\t'.join(content_text_split[2:])
            global_thread[_type][task_id]['conversation_id'] = content_text_split[1]
            global_thread[_type][task_id]['task_id'] = content_text_split[0]
            answer += reply
            yield reply
    except StopIteration as e:

        print(traceback.format_exc())

        try:
            conversation_id, sql_md, results = e.value
            global_thread[_type][task_id]['sql_md'] = sql_md
            # global_thread[_type][task_id]['conversation_id'] = conversation_id
            global_thread[_type][task_id]['results'] = results
        except:
            pass


#流式接口
def chat_stream_resonese(request):
    if request.method == 'GET':

        # 从请求中获取参数，假设参数名为 'param'
        task_id = request.GET.get('task_id')
        _type = request.GET.get('type')

        # 任务id不能为空
        if not task_id:
            res = {
                'code': 0,
                'msg': "任务id不能为空。"
            }
            return JsonResponse(res)

        if not _type:
            res = {
                'code': 0,
                'msg': "任务类型不能为空。"
            }
            return JsonResponse(res)

        if _type not in ['chat']:
            res = {
                'code': 0,
                'msg': "任务类型只能为chat。"
            }
            return JsonResponse(res)

        #任务id不存在
        if task_id not in global_thread[_type].keys():
            res = {
                'code': 0,
                'msg': "任务id不存在。"
            }
            return JsonResponse(res)

        #线程如果存活，代表任务处理中
        if global_thread[_type][task_id]['job'].is_alive():
            res = {
                "code": 0,
                'msg': '任务处理中...'
            }
            return JsonResponse(res)

        #重新将输出置为True
        global_thread[_type][task_id]['stream'] = True

        response = StreamingHttpResponse(stream_response(_type,task_id), content_type='text/event-stream; charset=utf-8')
        return response
    else:
        res = {
            'code': 0,
            'msg': "不支持的请求方法"
        }
        return JsonResponse(res)

#终止输出
def stop_stream_response(request):

    if request.method == 'GET':

        # 从请求中获取参数，假设参数名为 'param'
        task_id = request.GET.get('task_id')
        _type = request.GET.get('type')

        # 任务id不能为空
        if not task_id:
            res = {
                'code': 0,
                'msg': "任务id不能为空。"
            }
            return JsonResponse(res)

        if not _type:
            res = {
                'code': 0,
                'msg': "任务类型不能为空。"
            }
            return JsonResponse(res)

        if _type not in ['chat']:
            res = {
                'code': 0,
                'msg': "任务类型只能为chat。"
            }
            return JsonResponse(res)

        #任务id不存在
        if task_id not in global_thread[_type].keys():
            res = {
                'code': 0,
                'msg': "任务id不存在。"
            }
            return JsonResponse(res)

        # 标识是否持续流式输出
        global_thread[_type][task_id]['stream'] = False

        result = dify_stop(global_thread[_type][task_id]['task_id'])

        if result:
            res = {
                'code': 1,
                'msg': '已停止'
            }
        else:
            res = {
                'code': 0,
                'msg': '停止失败'
            }
        return JsonResponse(res)
    else:
        res = {
            'code': 0,
            'msg': "不支持的请求方法"
        }
        return JsonResponse(res)